﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace CategoryTest.ViewModel
{
    /// <summary>
    /// 一个通用的 ICommand 实现
    /// </summary>
    public class RelayCommand<T> : ICommand
    {
        private readonly Action<T> _execute;
        private readonly Predicate<T> _canExecute;

        /// <summary>
        /// 初始化 RelayCommand
        /// </summary>
        /// <param name="execute">命令执行的动作</param>
        public RelayCommand(Action<T> execute) : this(execute, null)
        {
        }

        /// <summary>
        /// 初始化 RelayCommand
        /// </summary>
        /// <param name="execute">命令执行的动作</param>
        /// <param name="canExecute">判断命令是否可执行的谓词</param>
        public RelayCommand(Action<T> execute, Predicate<T> canExecute)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        /// <summary>
        /// 判断命令是否可以执行
        /// </summary>
        public bool CanExecute(object parameter)
        {
            // 检查参数类型是否匹配，或者是否允许 null
            if (_canExecute == null) return true;

            if (parameter == null && typeof(T).IsValueType)
            {
                // 如果 T 是值类型，而参数是 null，通常不能执行
                // 但如果 T 是 Nullable<U>，则可以
                return typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>);
            }

            if (parameter != null && !(parameter is T))
            {
                // 如果参数不为 null 但类型不匹配，不能执行
                return false;
            }

            return _canExecute((T)parameter);
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        public void Execute(object parameter)
        {
            // 确保参数类型正确或为 null（如果允许）
            if (parameter == null && typeof(T).IsValueType)
            {
                // 对于非 Nullable 值类型，参数不能为 null
                if (!(typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>)))
                {
                    // 或者在这里抛出异常，或者根据需要处理
                    return; // 或者默认行为？取决于具体命令
                }
            }

            if (parameter != null && !(parameter is T))
            {
                // 类型不匹配，不执行
                return;
            }

            _execute((T)parameter);
        }


        /// <summary>
        /// 当 CanExecute 的条件可能改变时触发此事件
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        /// <summary>
        /// 手动触发 CanExecuteChanged 事件（如果需要精确控制）
        /// </summary>
        public void RaiseCanExecuteChanged()
        {
            CommandManager.InvalidateRequerySuggested();
        }
    }

    /// <summary>
    /// 无参数的 RelayCommand
    /// </summary>
    public class RelayCommand : RelayCommand<object>
    {
        public RelayCommand(Action execute) : base(param => execute(), null)
        {
        }

        public RelayCommand(Action execute, Func<bool> canExecute) : base(param => execute(), param => canExecute())
        {
        }
    }
}
